package course.examples.Touch.LocateTouch;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.Random;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.FrameLayout;
public class IndicateTouchLocationActivity extends Activity {
private static final int MIN_DXDY = 2;
// Assume no more than 20 simultaneous touches
final private static int MAX_TOUCHES = 20;
// Pool of MarkerViews
final private static LinkedList<MarkerView> mInactiveMarkers = new LinkedList<MarkerView>();
// Set of MarkerViews currently visible on the display
@SuppressLint("UseSparseArrays")
final private static Map<Integer, MarkerView> mActiveMarkers = new HashMap<Integer, MarkerView>();
protected static final String TAG = "IndicateTouchLocationActivity";
private FrameLayout mFrame;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mFrame = (FrameLayout) findViewById(R.id.frame);
// Initialize pool of View.
initViews();
// Create and set on touch listener
mFrame.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getActionMasked()) {
// Show new MarkerView
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_POINTER_DOWN: {
int pointerIndex = event.getActionIndex();
int pointerID = event.getPointerId(pointerIndex);
MarkerView marker = mInactiveMarkers.remove();
if (null != marker) {
mActiveMarkers.put(pointerID, marker);
marker.setXLoc(event.getX(pointerIndex));
marker.setYLoc(event.getY(pointerIndex));
updateTouches(mActiveMarkers.size());
mFrame.addView(marker);
}
break;
}
// Remove one MarkerView
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_POINTER_UP: {
int pointerIndex = event.getActionIndex();
int pointerID = event.getPointerId(pointerIndex);
MarkerView marker = mActiveMarkers.remove(pointerID);
if (null != marker) {
mInactiveMarkers.add(marker);
updateTouches(mActiveMarkers.size());
mFrame.removeView(marker);
}
break;
}
// Move all currently active MarkerViews
case MotionEvent.ACTION_MOVE: {
for (int idx = 0; idx < event.getPointerCount(); idx++) {
int ID = event.getPointerId(idx);
MarkerView marker = mActiveMarkers.get(ID);
if (null != marker) {
// Redraw only if finger has travel ed a minimum distance
if (Math.abs(marker.getXLoc() - event.getX(idx)) > MIN_DXDY
|| Math.abs(marker.getYLoc()
- event.getY(idx)) > MIN_DXDY) {
// Set new location
marker.setXLoc(event.getX(idx));
marker.setYLoc(event.getY(idx));
// Request re-draw
marker.invalidate();
}
}
}
break;
}
default:
Log.i(TAG, "unhandled action");
}
return true;
}
// update number of touches on each active MarkerView
private void updateTouches(int numActive) {
for (MarkerView marker : mActiveMarkers.values()) {
marker.setTouches(numActive);
}
}
});
}
private void initViews() {
for (int idx = 0; idx < MAX_TOUCHES; idx++) {
mInactiveMarkers.add(new MarkerView(this, -1, -1));
}
}
private class MarkerView extends View {
private float mX, mY;
final static private int MAX_SIZE = 400;
private int mTouches = 0;
final private Paint mPaint = new Paint();
public MarkerView(Context context, float x, float y) {
super(context);
mX = x;
mY = y;
mPaint.setStyle(Style.FILL);
Random rnd = new Random();
mPaint.setARGB(255, rnd.nextInt(256), rnd.nextInt(256),
rnd.nextInt(256));
}
float getXLoc() {
return mX;
}
void setXLoc(float x) {
mX = x;
}
float getYLoc() {
return mY;
}
void setYLoc(float y) {
mY = y;
}
void setTouches(int touches) {
mTouches = touches;
}
@Override
protected void onDraw(Canvas canvas) {
canvas.drawCircle(mX, mY, MAX_SIZE / mTouches, mPaint);
}
}
}